package cn.hg.solon.youcan.system.provider;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.copier.CopyOptions;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.text.CharSequenceUtil;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.db.PageResult;
import org.noear.solon.annotation.ProxyComponent;
import org.noear.solon.data.annotation.Tran;

import com.easy.query.api4j.client.EasyQuery;
import com.easy.query.api4j.select.Queryable;
import com.easy.query.core.api.pagination.EasyPageResult;
import com.easy.query.solon.annotation.Db;

import cn.hg.solon.youcan.common.constant.WebConstants;
import cn.hg.solon.youcan.common.enums.OnlineStatus;
import cn.hg.solon.youcan.system.entity.EqUserOnline;
import cn.hg.solon.youcan.system.entity.UserOnline;
import cn.hg.solon.youcan.system.service.UserOnlineService;

/**
 * @author 胡高
 * @date 2023/08/03
 */
@ProxyComponent
public class EqUserOnlineProvider implements UserOnlineService {

    @Db("db1")
    private EasyQuery easyQuery;

    private Queryable<EqUserOnline> buildQuery(Map<String, Object> map) {
        String word = (String)map.get("word");
        String status = (String)map.get("status");
        Date startDate = (Date)map.get("startDate");
        Date endDate = (Date)map.get("endDate");
        String sortField = (String)map.get("sortField");
        String sortType = (String)map.get("sortType");

        boolean customOrderBy = StrValidator.isNotBlank(sortField) && StrValidator.isNotBlank(sortType);

        // FROM sys_user_online AS t
        return this.easyQuery.queryable(EqUserOnline.class)
            // WHERE t.`status` = ${status} AND t.`start_datetime` > ${startDate} AND t.`start_datetime` < ${endDate}
            .where(w -> w.eq(StrValidator.isNotBlank(status), EqUserOnline::getStatus, status)
                .rangeClosed(EqUserOnline::getStartDatetime, ObjUtil.isNotNull(startDate), startDate, ObjUtil.isNotNull(endDate), endDate)
                // AND (t.`nickname` LIKE '%${word}%' OR t.`dept_name` LIKE '%${word}%' OR t.`ip` LIKE '%${word}%'
                //      OR t.`location` LIKE '%${word}%' OR t.`browser` LIKE '%${word}%' OR t.`os` LIKE '%${word}%'
                //      OR t.`id` LIKE '%${word}%')
                .and(StrValidator.isNotBlank(word),
                    a -> a.like(EqUserOnline::getNickname, word)
                    .or().like(EqUserOnline::getDeptName, word)
                    .or().like(EqUserOnline::getIp, word)
                    .or().like(EqUserOnline::getLocation, word)
                    .or().like(EqUserOnline::getBrowser, word)
                    .or().like(EqUserOnline::getOs, word)
                    .or().like(EqUserOnline::getId, word)
                    ))
            .orderBy(ob -> ob.sqlNativeSegment(customOrderBy ? CharSequenceUtil.toUnderlineCase(sortField) : "start_datetime"),
                (customOrderBy ? !CharSequenceUtil.equalsIgnoreCase(sortType, WebConstants.ORDER_DIRECTION_DESC) : Boolean.FALSE));
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#get(java.lang.String)
     */
    @Override
    public UserOnline get(String token) {
        return this.easyQuery.queryable(EqUserOnline.class).whereById(token).firstOrNull();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#insert(cn.hg.solon.youcan.system.entity.UserOnline)
     */
    @Tran
    @Override
    public boolean insert(UserOnline bean) {
        EqUserOnline cloneBean = BeanUtil.copyProperties(bean, EqUserOnline.class);

        return this.easyQuery.insertable(cloneBean).executeRows() > 0L;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#offline(java.lang.String)
     */
    @Tran
    @Override
    public boolean offline(String token) {
        return this.easyQuery.updatable(EqUserOnline.class)
            .set(EqUserOnline::getStatus, OnlineStatus.OFF.name())
            .whereById(token)
            .executeRows() > 0L;

    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#onlineList()
     */
    @Override
    public List<? extends UserOnline> onlineList() {
        return this.easyQuery.queryable(EqUserOnline.class)
            .where(w -> w.eq(EqUserOnline::getStatus, OnlineStatus.ON.name()))
            .toList();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#pageBy(int, int, java.util.Map)
     */
    @Override
    public PageResult<? extends UserOnline> pageBy(int pageNumber, int pageSize, Map<String, Object> paraMap) {
        EasyPageResult<EqUserOnline> pageList = this.buildQuery(paraMap).toPageResult(Convert.toLong(pageNumber), pageSize);

        PageResult<EqUserOnline> result = new PageResult<>();
        result.addAll(pageList.getData());
        result.setTotal(Convert.toInt(pageList.getTotal()));

        return result;
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#syncActivityTime(java.lang.String, java.util.Date)
     */
    @Tran
    @Override
    public void syncActivityTime(String token, Date datetime) {
        this.easyQuery.updatable(EqUserOnline.class)
        .set(EqUserOnline::getActivityDatetime, datetime)
        .whereById(token)
        .executeRows();
    }

    /* (non-Javadoc)
     * @see cn.hg.solon.youcan.system.service.UserOnlineService#update(cn.hg.solon.youcan.system.entity.UserOnline)
     */
    @Tran
    @Override
    public boolean update(UserOnline bean) {
        UserOnline cloneBean = this.get(bean.getId());

        BeanUtil.copyProperties(bean, cloneBean, CopyOptions.of().setIgnoreNullValue(true));

        return this.easyQuery.updatable(cloneBean).executeRows() > 0;
    }

}
